<?php
/**
 * Created By Leroi Liu
 * Email：675667823@qq.com
 * Date：2023/2/12
 * Description：
 **/
// 应用公共文件

if (!function_exists('array_to_tree')){
    function array_to_tree($list, $root = 0, $pk = 'id', $pid = 'pid', $child = 'children'): array
    {
        // 创建Tree
        $tree = array();
        if (is_array($list)) {
            // 创建基于主键的数组引用
            $refer = array();
            foreach ($list as $key => $data) {
                $refer[$data[$pk]] = &$list[$key];
            }
            foreach ($list as $key => $data) {
                // 判断是否存在parent
                $parentId = 0;
                if (isset($data[$pid])) {
                    $parentId = $data[$pid];
                }
                if ((string)$root == $parentId) {
                    $tree[] = &$list[$key];
                } else {
                    if (isset($refer[$parentId])) {
                        $parent = &$refer[$parentId];
                        $parent[$child][] = &$list[$key];
                    }
                }
            }
        }
        return $tree;
    }
}

if (!function_exists('tree_to_array')){
    function tree_to_array($tree = [], $children = 'children'): array
    {
        if (empty($tree) || !is_array($tree)) {
            return $tree;
        }
        $arrRes = [];
        foreach ($tree as $k => $v) {
            $arrTmp = $v;
            unset($arrTmp[$children]);
            $arrRes[] = $arrTmp;
            if (!empty($v[$children])) {
                $arrTmp = tree_to_array($v[$children]);
                $arrRes = array_merge($arrRes, $arrTmp);
            }
        }
        return $arrRes;
    }
}

if (!function_exists('array_rand_by_weight')){
    /**
     * @description 增加权重计算器
     * @param array $data
     * @param string $key
     * @return array|mixed
     */
    function array_rand_by_weight(array $data,string $key='weight'){
        if (empty($data)) return [];
        $w = [];
        foreach($data as $k => $v){
            if (!empty($v[$key])&&is_numeric($v[$key])){
                $w = array_merge($w,array_fill(0,intval($v[$key]),$k));
            }
        }
        if (!empty($w)){
            return $data[$w[array_rand($w)]];
        }
        return [];
    }
}
if (!function_exists('array_group_by')){
    /**
     * 数组按某一个元素值进行分组,正如数据库的group by语句
     * @param $array
     * @param $key
     * @return array
     */
    function array_group_by($array, $key): array
    {
        $res = [];
        foreach ($array as $item) {
            $res[$item[$key]][] = $item;
        }
        return $res;
    }
}

if (!function_exists('array_by_field')){
    function array_by_field($array, $keys=''): array
    {
        if (is_string($keys)&&strlen($keys)>0) $keys = explode(',', $keys);
        return array_reduce($keys, function ($acc, $key) use ($array) {
            $key = explode(' as ', $key);
            $key[0] = trim($key[0]??'')??'';
            $key[1] = trim($key[1]??'')??'';
            if (!empty($key[0])){
                $acc[!empty($key[1])?$key[1]:$key[0]] = $array[$key[0]]??'';
            }
            return $acc;
        }, []);
    }
}


if (!function_exists('getRangeDates')){
    function getRangeDates($date1,$date2,$include=''): array
    {
        $arr = [];
        if ($date1&&$date2){
            $date1 = is_numeric($date1)?$date1:strtotime(substr($date1??'',0,10));
            $date2 = is_numeric($date2)?$date2:strtotime(substr($date2??'',0,10));
            if ($date1>$date2){
                $date1 = $date1 + $date2;
                $date2 = $date1 - $date2;
                $date1 = $date1 - $date2;
            }
            if ($include === 'begin'){
                $date1 += 0;
                $date2 += 0;
            }elseif ($include == 'end'){
                $date1 += 3600*24;
                $date2 += 1;
            }else if ($include == 'both_none'){
                $date1 += 3600*24;
                $date2 += 0;
            }else{
                $date1 += 0;
                $date2 += 1;
            }
            while ($date1<$date2){
                $arr[]  = date('Y-m-d',$date1);
                $date1 += 3600*24;
            }
        }
        return $arr;
    }
}

if (!function_exists('formatDateTimeStampRange')){
    function formatDateTimeStampRange($key,$date_start,$date_end,array $options=[]): array
    {
        //格式化数据
        if (is_numeric($date_start)&&$date_start>0&&is_numeric($date_end)&&$date_end>0){
            $date_start = substr($date_start,0,10);
            $date_end = substr($date_end,0,10);
        }elseif (is_string($date_start)&&preg_match("/\d{4}\D*\d{2}\D*\d{2}/",$date_start,$date_start)&&is_string($date_end)&&preg_match("/\d{4}\D*\d{2}\D*\d{2}/",$date_end,$date_end)){
            $options['start_point'] = $options['start_point']??'00:00:00';
            if (!is_string($options['start_point'])) $options['start_point'] = '00:00:00';
            $options['end_point'] = $options['end_point']??'23:59:59';
            if (!is_string($options['end_point'])) $options['end_point'] = '23:59:59';
            $date_start = strtotime("{$date_start[0]} {$options['start_point']}");
            $date_end = strtotime("{$date_end[0]} {$options['end_point']}");
        }else{
            return [];
        }
        //确认符号
        $start_symbol = $options['start_symbol']??'';
        if (!in_array($start_symbol,['>','>='])) $start_symbol = '>=';
        $end_symbol = $options['end_symbol']??'';
        if (!in_array($end_symbol,['<','<='])) $end_symbol = '<=';
        //调换大小和顺序
        if ($date_start>$date_end){
            $date_start = $date_start + $date_end;
            $date_end = $date_start - $date_end;
            $date_start = $date_start - $date_end;
        }
        //返回结果
        return [
            [$key,$start_symbol,$date_start],
            [$key,$end_symbol,$date_end],
        ];
    }
}

if (!function_exists('http_build_full_url')){
    function http_build_full_url($url,$options = []) :string
    {
        $url = is_string($url)?$url:'';
        $url = parse_url($url??'');
        parse_str($url['query']??'',$url['query']);
        $options = is_array($options)?$options:[];
        foreach ($options as $key => $option){
            if (empty($option)) continue;
            if ($key==='query'){
                $url[$key] = array_merge(is_array($url[$key])?$url[$key]:[],is_array($option)?$option:[]);
            }else{
                $url[$key] = $option;
            }
        }
        $url['query'] = array_filter(is_array($url['query'])?$url['query']:[]);
        $url['query'] = http_build_query($url['query']);
        return sprintf('%s%s%s%s%s%s',
            !empty($url['scheme'])?"{$url['scheme']}://":'',
            $url['host'] ?? '',
            !empty($url['port']) ? ":{$url['port']}" : '',
            $url['path'] ?? '',
            !empty($url['query']) ? '?' . $url['query'] : '',
            !empty($url['fragment']) ? '#' . $url['fragment'] : ''
        );
    }
}

if (!function_exists('accept_params')){
    function accept_params(array $key_def=[],string $accept_methods=''): array
    {
        if (is_string($accept_methods)&&preg_match_all('#GET|POST|PHP_INPUT#i',$accept_methods,$methods)){
            $methods = $methods[0];
            foreach ($methods as $k => $method) $methods[$k] = strtoupper($method);
        }else{
            $methods = ['GET','POST','PHP_INPUT'];
        }
        $input = array_reduce($methods,function ($carry,$method){
            if ($method === 'GET') return array_merge($carry,$_GET??[]);
            if ($method === 'POST') return array_merge($carry,$_POST??[]);
            if ($method === 'PHP_INPUT') return array_merge($carry,json_decode(file_get_contents('php://input')??'{}',true)??[]);
            return $carry;
        },[]);
        if (empty($key_def)) return [];
        $data = [];
        foreach ($key_def as $key => $def){
            $key = explode(' as ',trim($key));
            $key[0] = trim($key[0]??'')??'';
            $key[1] = trim($key[1]??'')??'';
            if (empty($key[0])) continue;
            $data[!empty($key[1])?$key[1]:$key[0]] = $input[$key[0]]??$def;
        }
        return $data;
    }
}
if (!function_exists('encryptDataSign')){
    /**
     * @param string $key
     * @param string $secret
     * @param array $data
     * @param int $isDev
     * @return string
     */
    function encryptDataSign(string $key, string $secret, array $data, int $isDev=0): string
    {
        $ST = mt_rand(0,9);
        $dt['isDev'] = $isDev;
        $dt['time'] = time();
        $dt['rand'] = mt_rand(1000,9999);
        $dt['data'] = $data;
        $dt = json_encode($dt,JSON_UNESCAPED_UNICODE+JSON_UNESCAPED_SLASHES);
        $dt = openssl_encrypt($dt, 'aes-256-cbc', $key,OPENSSL_CIPHER_RC2_40, substr($secret,$ST,16));
        return "KEY{$key}DATA{$ST}{$dt}";
    }
}
if (!function_exists('decryptDataSign')){
    /**
     * @param $data
     * @param callable $secretCb
     * @param callable $isOnceCb
     * @param int $expire
     * @return array|mixed
     * @throws Exception
     */
    function decryptDataSign($data, callable $secretCb, callable $isOnceCb, int $expire = 5){
        if (is_string($data)&&preg_match("/^KEY(\w+)DATA(\d)(.*)/",$data,$matches)){
            $matches = openssl_decrypt($matches[3], 'aes-256-cbc', $matches[1],OPENSSL_ZERO_PADDING, substr($secretCb($matches[1])??'',$matches[2],16));
            $matches = preg_replace('/[\x00-\x1F\x80-\xFF]+$/', '',$matches);
            $matches = json_decode($matches??'{}',true)??[];
            $matches['isDev'] = (isset($matches['isDev'])&&is_numeric($matches['isDev'])&&$matches['isDev']>0)?1:0;
            $matches['time'] = (isset($matches['time'])&&is_numeric($matches['time'])&&$matches['time']>0)?substr($matches['time'],0,10):0;
            if ($matches['isDev']<=0){
                if (abs(time()-$matches['time'])>$expire) throw new \Exception('[50010]网络连接超时，请检查网络后重试',50010);
                if (!$isOnceCb('OnlyOnce:Req:'.md5($data),$expire)) throw new Exception('[50011]网络连接超时，请检查网络后重试',50011);
            }
            return $matches['data']??[];
        }
        throw new Exception('[50012]网络验证失败，请检查网络后重试',50012);
    }
}

if (!function_exists('url_is_wechat_110')){
    function url_is_wechat_110($url): bool
    {
        if (preg_match("#^http#",$url)){
            $header = get_headers("http://mp.weixinbridge.com/mp/wapredirect?url={$url}",true);
            if (isset($header['Location'][0])){
                if (is_array($header['Location'])) $header['Location'] = implode(';',$header['Location']);
                if (is_string($header['Location'])&&strpos($header['Location'],'weixin110.qq.com')!==false){
                    return true;
                }
            }
        }
        return false;
    }
}